﻿/*********************************************************************
 *
 *                             NOTICE
 *               COPYRIGHT (c) 2012 Panoscopix Software, Inc.
 *                UNPUBLISHED - ALL RIGHTS RESERVED
 * 
 *      This program is confidential, proprietary, and a trade
 *   secret of Panoscopix Software, Inc. The receipt or possession of
 *     this program does not convey any rights to reproduce or
 *      disclose its contents, or to manufacture, use, or sell
 *       anything that it may describe, in whole or in part, 
 *   without the specific written consent of Panoscopix Software, Inc.
 *
 * A simple in-memory implementation of a Directory.
 * 
 *******************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using FileSystem;
using FileSystem.Utility;

namespace FileSystem.Impl
{
	class FSDirectory : IFSDirectory
	{
		private NodeMetaData metaData;
		private IFSDirectory  parent;
		private List<IFSNode> contained;
	
		public FSDirectory(INodeMetaDataVO metaData) {
			this.metaData = metaData.copy();
			parent = null;
			contained = new List<IFSNode>();
			this.metaData.size = contained.Count();
		}

		public IFSNode GetByName(string name)
		{
			int i = indexOfName(name);
			if (i >= 0)
			{
				return this.getNode(i);
			}

			return null;
		}
		public IFSDirectory getParent() {
			return parent;
		}

		public void setParent(IFSDirectory parent) {
			this.parent = parent;
		}

		public String getID() {
			return metaData.id;
		}
	
		public String getName() {
			return metaData.name;
		}

		public String getFQName() {
			if (null == parent) {
				if (StringUtil.isNullOrEmpty(getName())) {
					//this is root
					return "/";
				}
				return "[ORPHAN]/" + getName() + "/";
			}
			return parent.getFQName() + getName() + "/";
		}

		public void rename(String newName) {
			metaData.name = newName;
		}
	
		public int getSize() {
			return metaData.size;
		}
	
		public String getCreationTimestamp() {
			return metaData.getCreationTimestamp();
		}

		public String getContents() {
			StringBuilder rc = new StringBuilder();
			rc.Append("Contents of " + describe() + "\n");
			for (int i = 0; i < contained.Count(); i++) {
				rc.Append(contained[i].describe() + "\n");
			}
			return rc.ToString();
		}

		public String describe() {
			return "Dir  " + getName() + "(" + getID() + ":" + getParentID() +
				"), created = " + getCreationTimestamp() + ", size = " + getSize();
		}

		public String describe(IPrintContext context) {
			StringBuilder rc = new StringBuilder();
			rc.Append(context.getFormattedString(describe()));
			context.increaseIndent();
			for (int i = 0; i < contained.Count(); i++) {
				rc.Append(contained[i].describe(context));
			}
			context.decreaseIndent();
			return rc.ToString();
		}
	
		public int numNodes() {
			return contained.Count();
		}
	
		public IFSNode getNode(int i) {
			if ((i >= 0) && (i < contained.Count())) {
				return contained[i];
			}
			return null;
		}

		public bool addNode(IFSNode node) {
			if (null != node) {
				String name = node.getName();
				if (isValidName(name) && (indexOfName(name) == -1)) {
					node.setParent(this);
					contained.Add(node);
					metaData.size = contained.Count();
					return true;
				}
			}
			return false;
		}

		public IFSNode removeNode(String name) {
			int index = indexOfName(name);
			if (index != -1) {
				IFSNode rc = contained[index];
				contained.RemoveAt(index);
				rc.setParent(null);
				metaData.size = contained.Count();
				return rc;
			}
			return null;
		}

		private bool isValidName(String name) {
			if (StringUtil.isNullOrEmpty(name) ||
					StringUtil.startsWith(name, ".") ||
					StringUtil.startsWith(name, "/")) {
				return false;
			}
			return true;
		}

		private int indexOfName(String name) {
			for (int i = 0; i < contained.Count(); i++) {
				if (name.Equals(contained[i].getName())) {
					return i;
				}
			}
			return -1;
		}

		private String getParentID()
		{
			if (null == parent) return "null";
			return parent.getID();
		}

        #region IFSNode Members


        /// <summary>
        /// Accepts the specified visitor.
        /// </summary>
        /// <param name="visitor">The visitor.</param>
        public void Accept(INodeVisitor visitor)
        {
            visitor.VisitDirectory(this);
        }

        #endregion
    }
}
